﻿using AppMachine.Domain.LogicCom;
using AppMachine.EntityFrameworkCore.Repositories.PerpDev;
using PerpheralDevice.IRepository;
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;

namespace AppMachine.EntityFrameworkCore.Repositories.LogicCom;

/// <summary>
/// 应用逻辑组件仓储(根据应用逻辑组件配置，构建应用逻辑组件)
/// </summary>
public class AppComRepository : AppFramework.DesignMode.Singleton<AppComRepository>, IComRepository {

    public AppComConfigRepository ComConfigRepository { get; } = new();
    private readonly ConcurrentDictionary<string, AppCom> _DicComBase = new();
    private AppComRepository() { }

    private AppCom Load(string comID) {
        var tempConfig = ComConfigRepository.Query(comID);
        Type? tempType = Type.GetType(tempConfig.ComType);
        if (tempType != null) {
            object? tempObject = Activator.CreateInstance(tempType, PerpDevRepository.GetInstance(), tempConfig, this);
            return tempObject as AppCom;
        }
        return null;
    }

    private AppCom GetOrAdd([NotNull] string devID, [NotNull] string unitID, [NotNull] Type comType) {
        var tempComConfig = ComConfigRepository.Query(devID, unitID, comType.FullName!);

        if (tempComConfig == null) {
            AppComConfig tempAppComConfig = new AppComConfig().SetRepository(ComConfigRepository);
            tempAppComConfig.PerpDevID = devID;
            tempAppComConfig.PerpSeatID = unitID;
            tempAppComConfig.ComType = $"{comType.FullName!},{comType.Assembly.FullName}";
            tempAppComConfig.ComID = $"{comType}.{devID}.{unitID}";
            tempComConfig = tempAppComConfig.Save();
        }
        return this.GetByID<AppCom>(tempComConfig.ComID);
    }

    /// <summary>
    /// 根据组件应用ID获取组件
    /// </summary>
    /// <typeparam name="T">组件类型</typeparam>
    /// <param name="comID">组件应用ID</param>
    /// <returns></returns>
    public T GetByID<T>(string comID) where T : AppCom {
        AppCom tempAppCom = _DicComBase.GetOrAdd(comID, (tempComID) => {
            return this.Load(tempComID) as T;
        });

        return tempAppCom as T;
    }

    /// <summary>
    /// 根据外设ID，外设单元ID 获取或添加 原子应用组件
    /// </summary>
    /// <param name="devID">外设ID</param>
    /// <param name="unitID">外设单元ID</param>
    /// <param name="comType">原子应用组件类型(输入，输出，伺服)</param>
    /// <returns></returns>
    public T GetOrAdd<T>(string devID, string unitID) where T : AppCom {
        return this.GetOrAdd(devID, unitID, typeof(T)) as T;
    }

    public IEnumerable<T> GetAll<T>() where T : AppCom {
        ComConfigRepository.GetAll().ToList().ForEach(tempCom => {
            if (!this._DicComBase.ContainsKey(tempCom.ComID)) {
                this.Load(tempCom.ComID);
            }
        });

        return this._DicComBase.Values.OfType<T>();
    }

}
